package selectbox

import (
	"context"
	"fmt"
	"github.com/templui/templui/internal/components/button"
	"github.com/templui/templui/internal/components/icon"
	"github.com/templui/templui/internal/components/input"
	"github.com/templui/templui/internal/components/popover"
	"github.com/templui/templui/internal/utils"
	"strconv"
)

type contextKey string

var contentIDKey contextKey = "contentID"

type Props struct {
	ID         string
	Class      string
	Attributes templ.Attributes
	Multiple   bool
}

type TriggerProps struct {
	ID                string
	Class             string
	Attributes        templ.Attributes
	Name              string
	Form              string
	Disabled          bool
	HasError          bool
	Multiple          bool
	ShowPills         bool
	SelectedCountText string
}

type ValueProps struct {
	ID          string
	Class       string
	Attributes  templ.Attributes
	Placeholder string
	Multiple    bool
}

type ContentProps struct {
	ID                string
	Class             string
	Attributes        templ.Attributes
	NoSearch          bool
	SearchPlaceholder string
}

type GroupProps struct {
	ID         string
	Class      string
	Attributes templ.Attributes
}

type LabelProps struct {
	ID         string
	Class      string
	Attributes templ.Attributes
}

type ItemProps struct {
	ID         string
	Class      string
	Attributes templ.Attributes
	Value      string
	Selected   bool
	Disabled   bool
}

templ SelectBox(props ...Props) {
	{{
		var p Props
		if len(props) > 0 {
			p = props[0]
		}
		wrapperID := p.ID
		if wrapperID == "" {
			wrapperID = utils.RandomID()
		}
		contentID := fmt.Sprintf("%s-content", wrapperID)
		ctx = context.WithValue(ctx, contentIDKey, contentID)
	}}
	<div
		id={ wrapperID }
		class={ utils.TwMerge("select-container w-full relative", p.Class) }
		{ p.Attributes... }
	>
		{ children... }
	</div>
}

templ Trigger(props ...TriggerProps) {
	{{
		var p TriggerProps
		if len(props) > 0 {
			p = props[0]
		}
		contentID, ok := ctx.Value(contentIDKey).(string)
		if !ok {
			contentID = "fallback-select-content-id"
		}
		if p.ShowPills {
			p.Multiple = true
		}
	}}
	@popover.Trigger(popover.TriggerProps{
		For:         contentID,
		TriggerType: popover.TriggerTypeClick,
	}) {
		@button.Button(button.Props{
			ID:      p.ID,
			Type:    "button",
			Variant: button.VariantOutline,
			Class: utils.TwMerge(
				// Required class for JavaScript
				"select-trigger",
				// Base styles matching input
				"w-full h-9 px-3 py-1 text-base md:text-sm",
				"flex items-center justify-between",
				"rounded-md border border-input bg-transparent shadow-xs transition-[color,box-shadow] outline-none",
				// Dark mode background
				"dark:bg-input/30",
				// Selection styles
				"selection:bg-primary selection:text-primary-foreground",
				// Focus styles
				"focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px]",
				// Error/Invalid styles
				"aria-invalid:ring-destructive/20 aria-invalid:border-destructive dark:aria-invalid:ring-destructive/40",
				utils.If(p.HasError, "border-destructive ring-destructive/20 dark:ring-destructive/40"),
				p.Class,
			),
			Disabled: p.Disabled,
			Attributes: utils.MergeAttributes(
				templ.Attributes{
					"data-tui-selectbox-content-id":          contentID,
					"data-tui-selectbox-multiple":            strconv.FormatBool(p.Multiple),
					"data-tui-selectbox-show-pills":          strconv.FormatBool(p.ShowPills),
					"data-tui-selectbox-selected-count-text": p.SelectedCountText,
					"tabindex":                               "0",
					"aria-invalid":                           utils.If(p.HasError, "true"),
				},
			),
		}) {
			<input
				type="hidden"
				if p.Name != "" {
					name={ p.Name }
				}
				if p.Form != "" {
					form={ p.Form }
				}
				{ p.Attributes... }
			/>
			{ children... }
			<span class="pointer-events-none ml-1">
				@icon.ChevronDown(icon.Props{
					Size:  16,
					Class: "text-muted-foreground",
				})
			</span>
		}
	}
}

templ Value(props ...ValueProps) {
	{{ var p ValueProps }}
	if len(props) > 0 {
		{{ p = props[0] }}
	}
	<span
		if p.ID != "" {
			id={ p.ID }
		}
		class={ utils.TwMerge("block truncate select-value text-muted-foreground", p.Class) }
		if p.Placeholder != "" {
			data-tui-selectbox-placeholder={ p.Placeholder }
		}
		{ p.Attributes... }
	>
		if p.Placeholder != "" {
			{ p.Placeholder }
		}
		{ children... }
	</span>
}

templ Content(props ...ContentProps) {
	{{
		var p ContentProps
		if len(props) > 0 {
			p = props[0]
		}
		contentID, ok := ctx.Value(contentIDKey).(string)
		if !ok {
			contentID = "fallback-select-content-id"
		}
	}}
	@popover.Content(popover.ContentProps{
		ID:         contentID,
		Placement:  popover.PlacementBottomStart,
		Offset:     4,
		MatchWidth: true,
		DisableESC: !p.NoSearch,
		Class: utils.TwMerge(
			"p-1 select-content z-50 overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md",
			"min-w-[var(--popover-trigger-width)] w-[var(--popover-trigger-width)]",
			p.Class,
		),
		Attributes: utils.MergeAttributes(
			templ.Attributes{
				"role":     "listbox",
				"tabindex": "-1",
			},
			p.Attributes,
		),
		Exclusive: true,
	}) {
		if !p.NoSearch {
			<div class="sticky top-0 bg-popover p-1">
				<div class="relative">
					<span class="absolute left-3 top-1/2 -translate-y-1/2 text-muted-foreground z-10 pointer-events-none">
						@icon.Search(icon.Props{Size: 16})
					</span>
					@input.Input(input.Props{
						Type:        input.TypeSearch,
						Class:       "pl-8",
						Placeholder: utils.IfElse(p.SearchPlaceholder != "", p.SearchPlaceholder, "Search..."),
						Attributes: templ.Attributes{
							"data-tui-selectbox-search": "",
						},
					})
				</div>
			</div>
		}
		<div class="max-h-[300px] overflow-y-auto">
			{ children... }
		</div>
	}
}

templ Group(props ...GroupProps) {
	{{ var p GroupProps }}
	if len(props) > 0 {
		{{ p = props[0] }}
	}
	<div
		if p.ID != "" {
			id={ p.ID }
		}
		class={ utils.TwMerge("p-1", p.Class) }
		role="group"
		{ p.Attributes... }
	>
		{ children... }
	</div>
}

templ Label(props ...LabelProps) {
	{{ var p LabelProps }}
	if len(props) > 0 {
		{{ p = props[0] }}
	}
	<span
		if p.ID != "" {
			id={ p.ID }
		}
		class={ utils.TwMerge("px-2 py-1.5 text-sm font-medium", p.Class) }
		{ p.Attributes... }
	>
		{ children... }
	</span>
}

templ Item(props ...ItemProps) {
	{{ var p ItemProps }}
	if len(props) > 0 {
		{{ p = props[0] }}
	}
	<div
		if p.ID != "" {
			id={ p.ID }
		}
		class={
			utils.TwMerge(
				"select-item relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 px-2 text-sm font-light outline-none",
				"hover:bg-accent hover:text-accent-foreground",
				"focus:bg-accent focus:text-accent-foreground",
				utils.If(p.Selected, "bg-accent text-accent-foreground"),
				utils.If(p.Disabled, "pointer-events-none opacity-50"),
				p.Class,
			),
		}
		role="option"
		data-tui-selectbox-value={ p.Value }
		data-tui-selectbox-selected={ strconv.FormatBool(p.Selected) }
		data-tui-selectbox-disabled={ strconv.FormatBool(p.Disabled) }
		tabindex="0"
		{ p.Attributes... }
	>
		<span class="truncate select-item-text">
			{ children... }
		</span>
		<span
			class={
				utils.TwMerge(
					"select-check absolute right-2 flex h-3.5 w-3.5 items-center justify-center",
					utils.IfElse(p.Selected, "opacity-100", "opacity-0"),
				),
			}
		>
			@icon.Check(icon.Props{Size: 16})
		</span>
	</div>
}
